package rad.framework.testing;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import rad.framework.embedded.ContainerTestCase;
import rad.framework.seam.ActionMetadata;
import rad.framework.seam.AbstractPageBean.MenuMetadata;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PageflowTest extends ContainerTestCase {

	protected static final Log log = LogFactory.getLog(PageflowTest.class);
	
	protected static final String PREFIX = "/jsf/";
	
	protected static final String EXTENSION = ".xhtml";

	protected Pageflow pageflow;

	protected Page addPage(String name, String viewId, String... actions) {
		return pageflow.addPage(name, viewId, actions);
	}
	
	protected static class Pageflow {
		private List<Page> pages = new ArrayList<Page>();

		public List<Page> getPages() {
			return pages;
		}

		public Page addPage(String name, String viewId, String... actions) {
			Page page = new Page(name, viewId, actions);
			pages.add(page);
			return  page;
		}
	}

	protected static class Page {

		private String name;
		private String viewId;
		private List<String> actions = new ArrayList<String>();
		private Map<String, String> values = new HashMap<String, String>();

		public Page(String name, String viewId, String... actions) {
			this.name = name;
			this.viewId = viewId;
			for (String action : actions) {
				this.actions.add(action);
			}
		}

		public String getName() {
			return name;
		}

		public String getViewId() {
			return viewId;
		}

		public List<String> getActions() {
			return actions;
		}

		public void addValue(String expression, String value) {
			values.put(expression, value);
		}
		
		public Map<String, String> getValues() {
			return values;
		}
	}

	public PageflowTest(String name) {
		super(name);
		pageflow = new Pageflow();
	}

	protected void setUp() throws Exception {
		super.setUp();
		login("user", "user");
	}

	public void testPageflow() throws Exception {
		String conversationId = null;
		for (final Page page : pageflow.getPages()) {
			log.debug("Page: " + page.getName());
			for (final String action : page.getActions()) {
				log.debug("Action: " + action);
				log.debug("Conversation ID: " + conversationId);
				conversationId = new FacesRequest(page.getViewId(),
						conversationId) {
					protected void renderResponse() throws Exception {
						log.debug("Page Label: " + getValue("#{" + page.getName() + ".label}"));
						List<MenuMetadata> menus = (List<MenuMetadata>) getValue("#{"
								+ page.getName() + ".menus}");
						for (MenuMetadata menu : menus) {
							log.debug("Menu: " + menu.getValue());
							log.debug("Menu Label: " + menu.getLabel());
							log.debug("Menu Title: " + menu.getTitle());
							log.debug("Menu Rendered: " + menu.isRendered());
							log.debug("Menu Disabled: " + menu.isDisabled());
							log.debug("Menu Icon: " + menu.getIcon());
						}
						List<ActionMetadata> actions = (List<ActionMetadata>) getValue("#{"
								+ page.getName() + ".actions}");
						for (ActionMetadata action : actions) {
							log.debug("Action: " + action.getValue());
							log.debug("Action Label: " + action.getLabel());
							log.debug("Action Title: " + action.getTitle());
							log.debug("Action Rendered: " + action.isRendered());
							log.debug("Action Disabled: " + action.isDisabled());
						}
					}
				}.run();
				conversationId = new FacesRequest(page.getViewId(),
						conversationId) {

					protected void updateModelValues() throws Exception {
						Map<String, String> values = page.getValues();
						for (Entry<String, String> entry : values.entrySet()) {
							String v = entry.getValue();
							Object value = v;
							if (v.startsWith("#{")) {
								value = getValue(v);
							}
							setValue(entry.getKey(), value);
						}
					}

					protected void invokeApplication() throws Exception {
						invokeAction("#{" + page.getName() + "." + action + "}");
					}
				}.run();
			}
		}
	}
}
